/***********************************************************

Filename: GeometryTools.h

Description:

Collection of computational geometry tools: check if a point is inside of a
triangle or a polygon, project a point to a plane, distance between point and
line/plane, span a plane from 3 points

Author: Shaoting Zhang

***********************************************************/

#ifndef _GEOMETRYTOOLS_H__
#define _GEOMETRYTOOLS_H__

#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include "TriMesh.h"//#include "GUA_OM.h"
//#include "Vec.h"

class GeometryTools
{
public:
	GeometryTools(void);
	~GeometryTools(void);

	// Check if point is inside of a triangle: http://mathworld.wolfram.com/TriangleInterior.html
	// p0, p1 and p2: three points consisting of a triangle; p: point in the same plane
	// return true if it's inside
	static bool isInsideOfTriangle(TriMesh::Point &p0, TriMesh::Point &p1, TriMesh::Point &p2, float p[]);
	static bool isInsideOfTriangle(TriMesh::Point &p0, TriMesh::Point &p1, TriMesh::Point &p2, double p[]);
	// point-line distance: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
	// p1 and p2: two points consisting of a line; p: point in the space
	// return the distance between p and this line
	static double distPoint2Line(TriMesh::Point &p1, TriMesh::Point &p2, float p[]);
	static double distPoint2Line(TriMesh::Point &p1, TriMesh::Point &p2, double p[]);
	// point-plane distance: http://mathworld.wolfram.com/Point-PlaneDistance.html
	// plane[4]: plane parameters, ax+by+cz+d=0, p: point in the space
	// return the SIGNED distance between p and plane
	static double distPoint2Plane(double plane[4], TriMesh::Point &p);
	// Given three points, span the plan by cross product
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/linefacet/
	// p1, p2 and p3: three points in space; result: abcd in ax+by+cz+d=0
	//static void spanPlane(qglviewer::Vec &p1, qglviewer::Vec &p2, qglviewer::Vec &p3, double result[4]);
	static void spanPlane(TriMesh::Point &p1, TriMesh::Point &p2, TriMesh::Point &p3, double result[4]);
	// project a point in 3d space to a plane, which is defined as ax+by+cz+d=0
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/linefacet/
	// plane[4]: ax+by+cz+d=0; p1: a point in space; p: project p1 to the plane
	static void projectPoint2Plane(double plane[4], TriMesh::Point &p1, TriMesh::Point &p);
	// check if point is inside of polygon
	// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/isInsideOfPolygon.html
	// vertx and verty: vertices on polygon; testx and testy: test polygon; nvert: number of vertices
	static int isInsideOfPolygon(int nvert, float *vertx, float *verty, float testx, float testy);
	// radius of inscribed circle
	// http://en.wikipedia.org/wiki/Incircle
	static double radiusOfInscribedCircle(TriMesh *mesh, TriMesh::FaceHandle &fh);
	// radius of circumscribed circle
	// http://en.wikipedia.org/wiki/Circumcircle
	static double radiusOfCircumscribedCircle(TriMesh *mesh, TriMesh::FaceHandle &fh);
	// return minimum angle in the triangle represented by fh
	static double minAngleInTriangle(TriMesh *mesh, TriMesh::FaceHandle &fh);
};
#endif
